home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / libs / libelf-0.5 / libelf-0 / libelf-0.5.2 / update.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-19  |  10.4 KB  |  415 lines

  1. /*
  2. update.c - implementation of the elf_update(3) function.
  3. Copyright (C) 1995 Michael Riepe <riepe@ifwsn4.ifw.uni-hannover.de>
  4.  
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9.  
  10. This library is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. Library General Public License for more details.
  14.  
  15. You should have received a copy of the GNU Library General Public
  16. License along with this library; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19.  
  20. #include <private.h>
  21.  
  22. static const unsigned short __encoding = ELFDATA2LSB + (ELFDATA2MSB << 8);
  23. #define native_encoding (*(unsigned char*)&__encoding)
  24.  
  25. #define rewrite(var,val,f)    \
  26.     do{if((var)!=(val)){(var)=(val);(f)|=ELF_F_DIRTY;}}while(0)
  27.  
  28. #define align(var,val)        \
  29.     do{if((val)>1){(var)+=(val)-1;(var)-=(var)%(val);}}while(0)
  30.  
  31. #define max(a,b)        ((a)>(b)?(a):(b))
  32.  
  33. static off_t
  34. _elf32_layout(Elf *elf, unsigned *flag) {
  35.     int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;
  36.     Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf->e_ehdr;
  37.     size_t off = 0;
  38.     unsigned version;
  39.     unsigned encoding;
  40.     size_t entsize;
  41.     unsigned shnum;
  42.     Elf_Scn *scn;
  43.  
  44.     *flag = elf->e_elf_flags | elf->e_phdr_flags;
  45.  
  46.     if ((version = ehdr->e_version) == EV_NONE) {
  47.     version = EV_CURRENT;
  48.     }
  49.     if (!valid_version(version)) {
  50.     seterr(ERROR_UNKNOWN_VERSION);
  51.     return -1;
  52.     }
  53.     if ((encoding = ehdr->e_ident[EI_DATA]) == ELFDATANONE) {
  54.     encoding = native_encoding;
  55.     }
  56.     if (!valid_encoding(encoding)) {
  57.     seterr(ERROR_UNKNOWN_ENCODING);
  58.     return -1;
  59.     }
  60.     entsize = _fsize32(version, ELF_T_EHDR); elf_assert(entsize);
  61.     rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags);
  62.     off = entsize;
  63.  
  64.     rewrite(ehdr->e_phnum, elf->e_phnum, elf->e_ehdr_flags);
  65.     if (elf->e_phnum) {
  66.     entsize = _fsize32(version, ELF_T_PHDR); elf_assert(entsize);
  67.     rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags);
  68.     if (layout) {
  69.         align(off, 4);
  70.         rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags);
  71.         off += elf->e_phnum * entsize;
  72.     }
  73.     else {
  74.         off = max(off, ehdr->e_phoff + elf->e_phnum * entsize);
  75.     }
  76.     }
  77.     else {
  78.     rewrite(ehdr->e_phentsize, 0, elf->e_ehdr_flags);
  79.     if (layout) {
  80.         rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags);
  81.     }
  82.     }
  83.  
  84.     for (scn = elf->e_scn_1, shnum = 0; scn; scn = scn->s_link, ++shnum) {
  85.     Elf32_Shdr *shdr = (Elf32_Shdr*)scn->s_shdr;
  86.     size_t scn_align = 1;
  87.     size_t len = 0;
  88.     Scn_Data *sd;
  89.  
  90.     elf_assert(shdr);
  91.  
  92.     *flag |= scn->s_scn_flags | scn->s_shdr_flags;
  93.  
  94.     if (scn->s_index != shnum) {
  95.         seterr(ERROR_SCNLIST_BROKEN);
  96.         return -1;
  97.     }
  98.  
  99.     if (scn->s_index == SHN_UNDEF) {
  100.         rewrite(shdr->sh_entsize, 0, scn->s_shdr_flags);
  101.         if (layout) {
  102.         rewrite(shdr->sh_offset, 0, scn->s_shdr_flags);
  103.         rewrite(shdr->sh_size, 0, scn->s_shdr_flags);
  104.         rewrite(shdr->sh_addralign, 0, scn->s_shdr_flags);
  105.         }
  106.         continue;
  107.     }
  108. #if 0
  109.     if (shdr->sh_type == SHT_NULL) {
  110.         continue;
  111.     }
  112. #endif
  113.     for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
  114.         size_t fsize, msize;
  115.  
  116.         if (shdr->sh_type == SHT_NOBITS) {
  117.         fsize = sd->sd_data.d_size;
  118.         }
  119.         else if (!valid_type(sd->sd_data.d_type)) {
  120.         /* can't translate */
  121.         fsize = sd->sd_data.d_size;
  122.         }
  123.         else {
  124.         msize = _msize32(sd->sd_data.d_version, sd->sd_data.d_type);
  125.         elf_assert(msize);
  126.         fsize = _fsize32(version, sd->sd_data.d_type);
  127.         elf_assert(fsize);
  128.         fsize = (sd->sd_data.d_size / msize) * fsize;
  129.         }
  130.  
  131.         if (layout) {
  132.         align(len, sd->sd_data.d_align);
  133.         scn_align = max(scn_align, sd->sd_data.d_align);
  134.         rewrite(sd->sd_data.d_off, (off_t)len, sd->sd_data_flags);
  135.         len += fsize;
  136.         }
  137.         else {
  138.         len = max(len, sd->sd_data.d_off + fsize);
  139.         }
  140.  
  141.         *flag |= sd->sd_data_flags;
  142.     }
  143.  
  144.     if (valid_scntype(shdr->sh_type)) {
  145.         Elf_Type type = _elf_scn_types[shdr->sh_type];
  146.         size_t fsize;
  147.  
  148.         elf_assert(valid_type(type));
  149.         if (type != ELF_T_BYTE) {
  150.         fsize = _fsize32(version, type);
  151.         elf_assert(fsize);
  152.         rewrite(shdr->sh_entsize, fsize, scn->s_shdr_flags);
  153.         }
  154.     }
  155.  
  156.     if (layout) {
  157.         align(off, scn_align);
  158.         rewrite(shdr->sh_offset, off, scn->s_shdr_flags);
  159.         rewrite(shdr->sh_size, len, scn->s_shdr_flags);
  160.         rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags);
  161.  
  162.         if (shdr->sh_type != SHT_NOBITS) {
  163.         off += len;
  164.         }
  165.     }
  166.     else if (len > shdr->sh_size) {
  167.         seterr(ERROR_SCN2SMALL);
  168.         return -1;
  169.     }
  170.     else if (shdr->sh_type != SHT_NOBITS) {
  171.         off = max(off, shdr->sh_offset + shdr->sh_size);
  172.     }
  173.     else {
  174.         off = max(off, shdr->sh_offset);
  175.     }
  176.     }
  177.  
  178.     rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags);
  179.     if (shnum) {
  180.     entsize = _fsize32(version, ELF_T_SHDR); elf_assert(entsize);
  181.     rewrite(ehdr->e_shentsize, entsize, elf->e_ehdr_flags);
  182.     if (layout) {
  183.         align(off, 4);
  184.         rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags);
  185.         off += shnum * entsize;
  186.     }
  187.     else {
  188.         off = max(off, ehdr->e_shoff + shnum * entsize);
  189.     }
  190.     }
  191.     else {
  192.     rewrite(ehdr->e_shentsize, 0, elf->e_ehdr_flags);
  193.     if (layout) {
  194.         rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags);
  195.     }
  196.     }
  197.  
  198.     rewrite(ehdr->e_ident[EI_MAG0], ELFMAG0, elf->e_ehdr_flags);
  199.     rewrite(ehdr->e_ident[EI_MAG1], ELFMAG1, elf->e_ehdr_flags);
  200.     rewrite(ehdr->e_ident[EI_MAG2], ELFMAG2, elf->e_ehdr_flags);
  201.     rewrite(ehdr->e_ident[EI_MAG3], ELFMAG3, elf->e_ehdr_flags);
  202.     rewrite(ehdr->e_ident[EI_CLASS], ELFCLASS32, elf->e_ehdr_flags);
  203.     rewrite(ehdr->e_ident[EI_DATA], encoding, elf->e_ehdr_flags);
  204.     rewrite(ehdr->e_ident[EI_VERSION], version, elf->e_ehdr_flags);
  205.     rewrite(ehdr->e_version, version, elf->e_ehdr_flags);
  206.  
  207.     *flag |= elf->e_ehdr_flags;
  208.  
  209.     return off;
  210. }
  211.  
  212. static off_t
  213. _elf32_write(Elf *elf, size_t len) {
  214.     Elf32_Ehdr *ehdr;
  215.     Elf32_Shdr *shdr;
  216.     Elf_Scn *scn;
  217.     Scn_Data *sd;
  218.     Elf_Data src;
  219.     Elf_Data dst;
  220.     unsigned encode;
  221.     size_t fsize;
  222.     size_t msize;
  223.     char *outbuf;
  224.  
  225.     if (!len) {
  226.     return len;
  227.     }
  228.  
  229.     if (!(outbuf = (char*)malloc(len))) {
  230.     seterr(ERROR_MEM_OUTBUF);
  231.     return -1;
  232.     }
  233.  
  234.     memset(outbuf, _elf_fill, len);
  235.  
  236.     ehdr = (Elf32_Ehdr*)elf->e_ehdr; elf_assert(ehdr);
  237.     encode = ehdr->e_ident[EI_DATA];
  238.  
  239.     src.d_buf = ehdr;
  240.     src.d_type = ELF_T_EHDR;
  241.     src.d_size = _msize32(_elf_version, ELF_T_EHDR);
  242.     src.d_version = _elf_version;
  243.     dst.d_buf = outbuf;
  244.     dst.d_size = ehdr->e_ehsize;
  245.     dst.d_version = ehdr->e_version;
  246.     if (!elf32_xlatetof(&dst, &src, encode)) {
  247.     free(outbuf);
  248.     return -1;
  249.     }
  250.  
  251.     if (ehdr->e_phnum) {
  252.     src.d_buf = elf->e_phdr;
  253.     src.d_type = ELF_T_PHDR;
  254.     src.d_size = ehdr->e_phnum * _msize32(_elf_version, ELF_T_PHDR);
  255.     src.d_version = _elf_version;
  256.     dst.d_buf = outbuf + ehdr->e_phoff;
  257.     dst.d_size = ehdr->e_phnum * ehdr->e_phentsize;
  258.     dst.d_version = ehdr->e_version;
  259.     if (!elf32_xlatetof(&dst, &src, encode)) {
  260.         free(outbuf);
  261.         return -1;
  262.     }
  263.     }
  264.  
  265.     for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
  266.     shdr = (Elf32_Shdr*)scn->s_shdr; elf_assert(shdr);
  267.     src.d_buf = shdr;
  268.     src.d_type = ELF_T_SHDR;
  269.     src.d_size = sizeof(*shdr);
  270.     src.d_version = EV_CURRENT;
  271.     dst.d_buf = outbuf + ehdr->e_shoff + scn->s_index * ehdr->e_shentsize;
  272.     dst.d_size = ehdr->e_shentsize;
  273.     dst.d_version = ehdr->e_version;
  274.     if (!elf32_xlatetof(&dst, &src, encode)) {
  275.         free(outbuf);
  276.         return -1;
  277.     }
  278.  
  279.     if (scn->s_index == SHN_UNDEF || shdr->sh_type == SHT_NOBITS) {
  280.         continue;
  281.     }
  282.     sd = NULL;
  283.     while ((sd = (Scn_Data*)elf_getdata(scn, (Elf_Data*)sd))) {
  284.         src = sd->sd_data;
  285.         if (!src.d_size) {
  286.         continue;
  287.         }
  288.         elf_assert(src.d_buf);
  289.         dst.d_buf = outbuf + shdr->sh_offset + src.d_off;
  290.         dst.d_size = src.d_size;
  291.         dst.d_version = ehdr->e_version;
  292.         if (valid_type(src.d_type)) {
  293.         msize = _msize32(src.d_version, src.d_type);
  294.         elf_assert(msize);
  295.         fsize = _fsize32(dst.d_version, src.d_type);
  296.         elf_assert(fsize);
  297.         dst.d_size = (dst.d_size / msize) * fsize;
  298.         }
  299.         else {
  300.         src.d_type = ELF_T_BYTE;
  301.         }
  302.         if (!elf32_xlatetof(&dst, &src, encode)) {
  303.         free(outbuf);
  304.         return -1;
  305.         }
  306.     }
  307.     }
  308.  
  309.     if (lseek(elf->e_fd, 0L, 0) == -1L) {
  310.     seterr(ERROR_IO_SEEK);
  311.     }
  312.     else if (write(elf->e_fd, outbuf, len) != (int)len) {
  313.     seterr(ERROR_IO_WRITE);
  314.     }
  315. #if HAVE_FTRUNCATE
  316.     else if (ftruncate(elf->e_fd, len) == -1) {
  317.     seterr(ERROR_IO_TRUNC);
  318.     }
  319. #endif
  320.     else {
  321.     elf->e_elf_flags &= ~ELF_F_DIRTY;
  322.     elf->e_ehdr_flags &= ~ELF_F_DIRTY;
  323.     elf->e_phdr_flags &= ~ELF_F_DIRTY;
  324.     for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
  325.         scn->s_scn_flags &= ~ELF_F_DIRTY;
  326.         scn->s_shdr_flags &= ~ELF_F_DIRTY;
  327.         for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
  328.         sd->sd_data_flags &= ~ELF_F_DIRTY;
  329.         }
  330.         if (elf->e_readable) {
  331.         shdr = (Elf32_Shdr*)scn->s_shdr;
  332.         elf_assert(shdr);
  333.         scn->s_type = shdr->sh_type;
  334.         scn->s_size = shdr->sh_size;
  335.         scn->s_offset = shdr->sh_offset;
  336.         }
  337.     }
  338.     if (elf->e_readable) {
  339.         elf_assert(elf->e_data);
  340.         elf_assert(!elf->e_parent);
  341.         elf_assert(len >= EI_NIDENT);
  342.         if (elf->e_rawdata) {
  343.         if (elf->e_data == elf->e_rawdata) {
  344.             elf->e_data = outbuf;
  345.         }
  346.         free(elf->e_rawdata);
  347.         elf->e_rawdata = outbuf;
  348.         }
  349.         else if (!elf->e_cooked) {
  350.         free(elf->e_data);
  351.         elf->e_data = outbuf;
  352.         }
  353.         else {
  354.         free(outbuf);
  355.         }
  356.         elf->e_size = len;
  357.         elf->e_class = ehdr->e_ident[EI_CLASS];
  358.         elf->e_encoding = ehdr->e_ident[EI_DATA];
  359.         elf->e_version = ehdr->e_ident[EI_VERSION];
  360.     }
  361.     else {
  362.         free(outbuf);
  363.     }
  364.     return len;
  365.     }
  366.     free(outbuf);
  367.     return -1;
  368. }
  369.  
  370. off_t
  371. elf_update(Elf *elf, Elf_Cmd cmd) {
  372.     unsigned flag;
  373.     off_t len;
  374.  
  375.     if (!elf) {
  376.     return -1;
  377.     }
  378.     elf_assert(elf->e_magic == ELF_MAGIC);
  379.     if (cmd == ELF_C_WRITE) {
  380.     if (!elf->e_writable) {
  381.         seterr(ERROR_RDONLY);
  382.         return -1;
  383.     }
  384.     if (elf->e_disabled) {
  385.         seterr(ERROR_FDDISABLED);
  386.         return -1;
  387.     }
  388.     }
  389.     else if (cmd != ELF_C_NULL) {
  390.     seterr(ERROR_INVALID_CMD);
  391.     return -1;
  392.     }
  393.  
  394.     if (!elf->e_ehdr) {
  395.     seterr(ERROR_NOEHDR);
  396.     }
  397.     else if (elf->e_kind != ELF_K_ELF) {
  398.     seterr(ERROR_NOTELF);
  399.     }
  400.     else if (elf->e_class == ELFCLASS32) {
  401.     len = _elf32_layout(elf, &flag);
  402.     if (len != -1 && cmd == ELF_C_WRITE && (flag & ELF_F_DIRTY)) {
  403.         len = _elf32_write(elf, len);
  404.     }
  405.     return len;
  406.     }
  407.     else if (valid_class(elf->e_class)) {
  408.     seterr(ERROR_UNIMPLEMENTED);
  409.     }
  410.     else {
  411.     seterr(ERROR_UNKNOWN_CLASS);
  412.     }
  413.     return -1;
  414. }
  415.